package app

import (
	"APT/internal/dao"
	"APT/internal/library/contexts"
	"APT/internal/library/hgorm/hook"
	"APT/internal/model/entity"
	"APT/internal/model/input/input_hotel"
	"APT/internal/service"
	"APT/utility/convert"
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"github.com/gogf/gf/v2/errors/gerror"

	"APT/api/app/hotel"
)

func (c *ControllerHotel) OrderList(ctx context.Context, req *hotel.OrderListReq) (res *hotel.OrderListRes, err error) {
	var (
		MemberUser   = contexts.GetMemberUser(ctx)
		AppStay      []*entity.PmsAppStay
		propertyInfo *input_hotel.PmsPropertyViewModel
	)
	res = new(hotel.OrderListRes)
	Where := g.MapStrAny{
		dao.PmsAppStay.Columns().MemberId: MemberUser.Id,
	}
	if !g.IsEmpty(req.OrderStatus) {
		Where[dao.PmsAppStay.Columns().OrderStatus] = req.OrderStatus
	}
	if err = dao.PmsAppStay.Ctx(ctx).Where(Where).
		OrderDesc(dao.PmsAppStay.Columns().Id).
		Page(req.PageNum, req.PageSize).
		ScanAndCount(&AppStay, &res.Count, false); err != nil && !errors.Is(err, sql.ErrNoRows) {
		return
	}
	if !g.IsEmpty(AppStay) {
		for _, v := range AppStay {
			if err = dao.PmsProperty.Ctx(ctx).Where(g.MapStrAny{
				dao.PmsProperty.Columns().Uid: v.Puid,
			}).Hook(hook.PmsFindLanguageValueHook).Scan(&propertyInfo); err != nil {
				err = errors.New("获取物业信息失败")
				return
			}
			CheckinDate := gtime.New(v.CheckInDate).Format("Y-m-d")
			CheckoutDate := gtime.New(v.CheckOutDate).Format("Y-m-d")
			Countdown := v.ExpirationTime - gvar.New(gtime.Now().Unix()).Int()
			if Countdown < 0 {
				Countdown = 0
			}
			item := &hotel.OrderItem{
				Id:              v.Id,
				OrderSn:         v.OrderSn,
				OrderStatus:     v.OrderStatus,
				CheckInDate:     CheckinDate,
				CheckOutDate:    CheckoutDate,
				Days:            convert.Diff(CheckinDate, CheckoutDate, "days"),
				PropertyName:    propertyInfo.Name,
				Address:         propertyInfo.Address,
				OrderAmount:     v.OrderAmount,
				RoomNum:         0,
				AdultCount:      0,
				ChildCount:      0,
				CreateOrderTime: gtime.New(v.CreatedAt).Format("Y-m-d H:i:s"),
				Countdown:       Countdown,
				RefundStatus:    v.RefundStatus,
			}
			if item.AdultCount, err = dao.PmsAppReservation.Ctx(ctx).Where(dao.PmsAppReservation.Columns().OrderSn, v.OrderSn).Sum(dao.PmsAppReservation.Columns().AdultCount); err != nil {
				return
			}
			if item.ChildCount, err = dao.PmsAppReservation.Ctx(ctx).Where(dao.PmsAppReservation.Columns().OrderSn, v.OrderSn).Sum(dao.PmsAppReservation.Columns().ChildCount); err != nil {
				return
			}
			if item.RoomNum, err = dao.PmsAppReservation.Ctx(ctx).Where(dao.PmsAppReservation.Columns().OrderSn, v.OrderSn).Count(dao.PmsAppReservation.Columns().Id); err != nil {
				return
			}
			ThirePayAmount := gvar.New(0)
			// 查询第三方支付金额
			if ThirePayAmount, err = dao.PmsTransaction.Ctx(ctx).
				Where(dao.PmsTransaction.Columns().OrderSn, v.OrderSn).
				Where("pay_channel != ?", "SYSTEM").
				Where(dao.PmsTransaction.Columns().PayStatus, "WAIT").
				Value(dao.PmsTransaction.Columns().Amount); err != nil {
				return
			}
			item.ThirePayAmount = ThirePayAmount.Float64()
			res.List = append(res.List, item)
		}
	}

	return
}
func (c *ControllerHotel) OrderDetail(ctx context.Context, req *hotel.OrderDetailReq) (res *hotel.OrderDetailRes, err error) {
	var (
		PmsPropertyInfo gdb.Record
		PmsPropertyView *input_hotel.PmsPropertyViewModel
		PmsRoomType     gdb.Record
		AppStay         *entity.PmsAppStay
		PmsGuestProfile *entity.PmsGuestProfile
		AppReservation  []*entity.PmsAppReservation
		AppTransaction  []*entity.PmsTransaction
		CancelOrderInfo *entity.PmsAppCancelOrder
		CheckinTime     string
		CheckoutTime    string
	)
	res = new(hotel.OrderDetailRes)
	res.OrderSn = req.OrderSn
	// 查询订单信息
	if err = dao.PmsAppStay.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsAppStay.Columns().OrderSn: req.OrderSn,
	}).Scan(&AppStay); err != nil {
		return
	}
	if g.IsEmpty(AppStay) {
		err = gerror.New("订单不存在")
		return
	}
	res.Id = AppStay.Id
	res.Countdown = gvar.New(gtime.Now().Unix()).Int() - AppStay.ExpirationTime
	res.CreateOrderTime = AppStay.CreatedAt.String()
	if err = dao.PmsGuestProfile.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsGuestProfile.Columns().Uid: AppStay.Booker,
	}).Scan(&PmsGuestProfile); err != nil {
		return
	}
	if g.IsEmpty(PmsGuestProfile) {
		err = gerror.New("订单信息异常")
		return
	}
	res.User.FullName = PmsGuestProfile.FullName
	res.User.Phone = PmsGuestProfile.Phone
	res.User.PhoneArea = PmsGuestProfile.AreaNo
	res.User.Mail = PmsGuestProfile.Email
	res.MemberId = PmsGuestProfile.MemberId
	// 查询物业信息
	if PmsPropertyInfo, err = dao.PmsProperty.Ctx(ctx).Where(dao.PmsProperty.Columns().Uid, AppStay.Puid).One(); err != nil {
		return
	}
	if PmsPropertyInfo.IsEmpty() {
		err = gerror.New("物业不存在")
	}
	if PmsPropertyView, _, err = service.HotelService().PropertyView(ctx, &input_hotel.PmsPropertyViewInp{
		Id: PmsPropertyInfo["id"].Int(),
	}); err != nil {
		return nil, err
	}
	res.Property.Cover = PmsPropertyView.Cover
	res.Property.Name = PmsPropertyView.Name
	res.Property.Address = PmsPropertyView.Address
	res.Property.RequiredBook = PmsPropertyView.RequiredBook
	res.OrderDate.StartDate = AppStay.CheckInDate
	res.OrderDate.EndDate = AppStay.CheckOutDate
	res.OrderDate.Days = convert.Diff(res.OrderDate.StartDate, res.OrderDate.EndDate, "days")
	// 查询房型订单信息
	if err = dao.PmsAppReservation.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsAppReservation.Columns().OrderSn: req.OrderSn,
	}).Scan(&AppReservation); err != nil {
		return
	}
	if g.IsEmpty(AppReservation) {
		err = gerror.New("订单房间信息不存在")
		return
	}
	for _, v := range AppReservation {
		// 查询房型信息
		if PmsRoomType, err = dao.PmsRoomType.Ctx(ctx).Hook(hook.PmsFindLanguageValueHook).Where(dao.PmsRoomType.Columns().Uid, v.RoomType).One(); err != nil {
			return
		}
		if PmsRoomType.IsEmpty() {
			err = gerror.Newf("房型不存在")
			return
		}
		res.CheckinStatus = v.CheckinStatus
		RoomTypeInfo := &input_hotel.OrderRooms{
			RoomId:     v.RoomType,
			Cover:      PmsRoomType["cover"].String(),
			Name:       PmsRoomType["name"].String(),
			RoomNum:    1,
			Adult:      v.AdultCount,
			Child:      v.ChildCount,
			BookingFee: 0,
		}
		// 查询房型价格
		if err = dao.PmsCharge.Ctx(ctx).Where(g.MapStrAny{
			dao.PmsCharge.Columns().Uid: v.Charges,
		}).Scan(&RoomTypeInfo.Charges); err != nil {
			return
		}
		RoomTypeInfo.BookingFee = v.BookingFee
		res.RatePlans = append(res.RatePlans, RoomTypeInfo)
		CheckinTime = v.CheckinTime
		CheckoutTime = v.CheckoutTime
	}
	res.OrderDate.StartDate = fmt.Sprintf("%s %s", res.OrderDate.StartDate, CheckinTime)
	res.OrderDate.EndDate = fmt.Sprintf("%s %s", res.OrderDate.EndDate, CheckoutTime)
	res.PayInfo.PayModel = AppStay.PayModel
	res.PayInfo.AllAmount = AppStay.OrderAmount
	res.PayInfo.OrderStatus = AppStay.OrderStatus
	res.PayInfo.RefundStatus = AppStay.RefundStatus

	if err = dao.PmsTransaction.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsTransaction.Columns().OrderSn: req.OrderSn,
	}).Scan(&AppTransaction); err != nil {
		return
	}
	for _, v := range AppTransaction {
		switch v.PayChannel {
		case "SYSTEM":
			if v.PayType == "BAL" {
				res.PayInfo.Balance.BalanceAmount = v.Amount
				res.PayInfo.Balance.BalancePayOrderSn = v.TransactionSn
				res.PayInfo.Balance.PayStatus = v.PayStatus
				res.PayInfo.Balance.RefundAmount = v.RefundAmount
				res.PayInfo.Balance.RefundStatus = v.RefundStatus
			}
			if v.PayType == "COUPON" {
				res.PayInfo.Coupon.CouponAmount = v.Amount
				res.PayInfo.Coupon.CouponPayOrderSn = v.TransactionSn
				res.PayInfo.Coupon.PayStatus = v.PayStatus
				res.PayInfo.Coupon.RefundAmount = v.RefundAmount
				res.PayInfo.Coupon.RefundStatus = v.RefundStatus
			}
		case "PAYCLOUD", "STRIPE", "PAYPAL":
			res.PayInfo.ThirdPay.ThirdAmount = v.Amount
			res.PayInfo.ThirdPay.ThirdPayOrderSn = v.TransactionSn
			res.PayInfo.ThirdPay.PayStatus = v.PayStatus
			res.PayInfo.ThirdPay.RefundAmount = v.RefundAmount
			res.PayInfo.ThirdPay.RefundStatus = v.RefundStatus
		}
	}
	// 查询是否存在退款订单
	if err = dao.PmsAppCancelOrder.Ctx(ctx).Where(dao.PmsAppCancelOrder.Columns().OrderSn, req.OrderSn).Scan(&CancelOrderInfo); err != nil && errors.Is(err, sql.ErrNoRows) {
		return
	}
	if !g.IsEmpty(CancelOrderInfo) {
		if res.RefundDetail, err = service.HotelService().RefundOrderDetail(ctx, &input_hotel.RefundDetailInp{OrderSn: req.OrderSn}); err != nil {
			return
		}
	}
	if AppStay.OrderStatus == "WAIT_PAY" {
		res.PayAmount = res.PayInfo.AllAmount - res.PayInfo.Balance.BalanceAmount - res.PayInfo.Coupon.CouponAmount
	} else {
		res.PayAmount = res.PayInfo.AllAmount
	}

	return
}
